<?php

namespace common\logics\trade\broadcast;

use Yii;
use yii\db\Exception;
use yii\helpers\ArrayHelper;
use common\models\trade\Trade;
use common\logics\trade\scope\CompatibleScopeShopOrder;
use common\logics\order\RecordOrderLog;
use common\models\shop\ShopOrder;
use common\models\shop\ShopOrderService;
use common\models\shop\ShopProductStats;

/**
 * 商城业务订单-支付回调通知处理
 *
 * @author emhome <emhome@163.com>
 * @since 2.0
 */
class ShopBroadcast extends BusinessNotifyBaseModel {

    /**
     * @var string 业务通知订单模型类名
     */
    public $modelClass = CompatibleScopeShopOrder::class;

    /**
     * 处理支付消息业务通知
     * @return bool
     */
    public function transactNotify() {
        /* @var $trade Trade */
        $trade = $this->trade;
        /* @var $order CompatibleScopeShopOrder */
        $order = $this->getOrderModel();

        $payCredit = intval($trade->credit * 10);
        $payAmount = $trade->total;

        $order->trade_id = $trade->id;
        $order->trade_no = $trade->trade_no;
        $order->pay_time = $trade->updated_at;
        $order->pay = $payAmount;
        $order->pay_credit = $payCredit;
        if ($order->status == CompatibleScopeShopOrder::STATUS_DEFAULT || $order->status == CompatibleScopeShopOrder::STATUS_ACTIVE) {
            $order->status = CompatibleScopeShopOrder::STATUS_PAID;
        }

        $shopOrders = $order->orders;
        $shopOrderGoods = $order->goods;
        $shopOrderDiscounts = $order->discounts;
        $goodsDiscounts = [];
        foreach ($shopOrderDiscounts as $orderDiscount) {
            if (isset($goodsDiscounts[$orderDiscount->order_goods_id])) {
                $goodsDiscounts[$orderDiscount->order_goods_id] += $orderDiscount->discount;
            } else {
                $goodsDiscounts[$orderDiscount->order_goods_id] = $orderDiscount->discount;
            }
        }
        if (!$order->save()) {
            Yii::error($order->getErrorMsg(), 'payment');
            throw new Exception('商城业务订单保存失败！');
        }
        $shopOrderCredits = [];
        $tempCredit = $payCredit;
        foreach ($shopOrders as $shopOrder) {
            $shopOrder->trade_id = $trade->id;
            $shopOrder->trade_no = $trade->trade_no;
            $shopOrder->pay_time = $trade->updated_at;
            $shopOrder->status = ShopOrder::STATUS_PAID;
            if ($payAmount > 0 && $payCredit > 0) {
                //计算订单积分比例按照向下取整方式，利于循环直接取舍，不用额外判断剩余积分是否大于0
                $curentCredit = ceil($shopOrder->pay / $payAmount * $payCredit);
                if ($curentCredit > $tempCredit) {
                    $curentCredit = $tempCredit;
                }
                $tempCredit -= $curentCredit;
                $shopOrder->pay_credit = $curentCredit;
                if ($shopOrder->pay) {
                    $shopOrderCredits[$shopOrder->id] = [
                        'rate' => $curentCredit / 10 / $shopOrder->pay,
                        'credits' => $curentCredit,
                        'residue' => $curentCredit,
                    ];
                }
            }
            if (!$shopOrder->save()) {
                throw new Exception('商城子订单保存失败！');
            }

            //生效订单商品退款服务信息
            $services = $shopOrder->inEffectiveOrderServices;
            foreach ($services as $service) {
                $service->setEnforce($shopOrder->pay_time);
                if ($service->order_status_end < $shopOrder->status) {
                    $service->status = ShopOrderService::STATUS_SUCCESS;
                }
                if (!$service->save()) {
                    throw new Exception('商城订单服务生效失败');
                }
            }

            //记录订单日志
            RecordOrderLog::safeRecord($shopOrder);
        }
        $productStats = [];
        foreach ($shopOrderGoods as $goods) {
            $goodsPayAmount = $goods->goods_price * $goods->goods_number;
            if (isset($goodsDiscounts[$goods->id])) {
                $goods->goods_discount = $goodsDiscounts[$goods->id];
                $goodsPayAmount -= $goods->goods_discount;
            }
            //当前订单商品最大可用积分数
            $goodsMaxUseCredits = $goods->getMaxDeductCredits();
            if ($goodsPayAmount > 0 && isset($shopOrderCredits[$goods->order_id])) {
                $shopOrderCredit = $shopOrderCredits[$goods->order_id];
                $orderResidueCredits = ArrayHelper::getValue($shopOrderCredit, 'residue');
                //剩余积分大于0时
                if ($orderResidueCredits > 0) {
                    $goodsUsedCredits = min(ceil($goodsPayAmount * ArrayHelper::getValue($shopOrderCredit, 'rate') * 10), $goodsMaxUseCredits);
                    $subtractOrderResidueCredits = $orderResidueCredits - $goodsUsedCredits;
                    if ($subtractOrderResidueCredits <= 0) {
                        $goodsUsedCredits = $orderResidueCredits;
                        $subtractOrderResidueCredits = 0;
                    }
                    $goods->pay_credit = $goodsUsedCredits;
                    ArrayHelper::setValue($shopOrderCredits, [$goods->order_id, 'residue'], $subtractOrderResidueCredits);
                }
            }
            if (!$goods->save()) {
                Yii::error($goods->getErrorMsg(), 'payment');
            }

            //更新商品统计信息
            $stats = ShopProductStats::findOrNew([
                'product_id' => $goods->product_id,
                'goods_id' => $goods->goods_id,
            ]);
            if (!isset($productStats[$goods->product_id])) {
                $productStats[$goods->product_id] = [
                    'product_id' => $goods->product_id,
                    'store_id' => $goods->store_id,
                    'nums' => 0,
                ];
            }
            if ($stats->isNewRecord) {
                $stats->sales = 0;
                $stats->store_id = $goods->store_id;
            }
            $productStats[$goods->product_id]['nums'] += $goods->goods_number;
            $stats->sales += $goods->goods_number;
            if (!$stats->save()) {
                Yii::error($stats->getErrorMsg(), 'payment');
            }
        }
        foreach ($productStats as $temp) {
            $stats = ShopProductStats::findOrNew([
                'product_id' => $temp['product_id'],
                'goods_id' => 0,
            ]);
            if ($stats->isNewRecord) {
                $stats->sales = 0;
                $stats->store_id = $temp['store_id'];
            }
            $stats->sales += $temp['nums'];
            if (!$stats->save()) {
                Yii::error($stats->getErrorMsg(), 'payment');
            }
        }
        return true;
    }

}
